﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using SpectrEngine.Framework.Collision;
using SpectrEngine.Framework.Collections;

namespace SpectrEngine.Framework
{

    public enum ScreenState
    {
        TransitionOn,
        Active,
        TransitionOff,
        Hidden,
    }

    public class GameScreen
        : DrawableGameNode
    {
        #region Fields

        private ScreenState state;

        public ScreenState State
        {
            get { return state; }
            set { state = value; }
        }

        protected TimeSpan transitionOnTime;

        public TimeSpan TransitionOnTime
        {
            get { return transitionOnTime; }
        }

        protected TimeSpan transitionOffTime;

        public TimeSpan TransitionOffTime
        {
            get { return transitionOffTime; }
        }

        protected float transitionPosition;

        public float TransitionPosition
        {
            get { return transitionPosition; }
        }

        protected SpriteBatch spriteBatch;

        public SpriteBatch SpriteBatch
        {
            get { return spriteBatch; }
        }

        protected UpdateList nodesToUpdate;

        public UpdateList NodesToUpdate
        {
            get { return nodesToUpdate; }
        }

        protected DrawList nodesToDraw;

        public DrawList NodesToDraw
        {
            get { return nodesToDraw; }
        }

        private bool blocksDraw;

        public bool BlocksDraw
        {
            get { return blocksDraw; }
            set { blocksDraw = value; }
        }

        private bool blocksUpdate;

        public bool BlocksUpdate
        {
            get { return blocksUpdate; }
            set { blocksUpdate = value; }
        }

        #endregion

        #region Local Variables

        protected CollisionManager collisionManager;

        protected Texture2D transitionMask;

        protected RenderTarget2D renderTarget;

        protected Effect transitionEffect;

        #endregion

        #region Constructors

        public GameScreen(Game game)
            : base(game, Vector2.Zero, 0.0f, Vector2.Zero)
        {
            state = ScreenState.TransitionOn;
            transitionPosition = 0.0f;

            transitionOnTime = TimeSpan.FromSeconds(2.0);
            transitionOffTime = TimeSpan.FromSeconds(2.0);

            nodesToUpdate = new UpdateList();
            nodesToDraw = new DrawList();

            PresentationParameters pp = Game.GraphicsDevice.PresentationParameters;

            spriteBatch = new SpriteBatch(game.GraphicsDevice);
            renderTarget = new RenderTarget2D(game.GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight, 1, SurfaceFormat.Color);
            transitionEffect = game.Content.Load<Effect>("Effects\\transition");

            collisionManager = new CollisionManager(game, new BoundingRect(Vector2.One * -100.0f, new Vector2(pp.BackBufferWidth + 100, pp.BackBufferHeight + 100)), 4);
        }

        #endregion

        #region Updating

        public override void Update(GameTime gameTime)
        {
            if (state == ScreenState.TransitionOn)
            {
                transitionPosition = MathHelper.Clamp(transitionPosition + gameTime.ElapsedGameTime.Milliseconds / (float)transitionOnTime.TotalMilliseconds, 0.0f, 1.0f);
                if (transitionPosition == 1.0f)
                {
                    state = ScreenState.Active;
                }
            }
            if (state == ScreenState.TransitionOff)
            {
                transitionPosition = MathHelper.Clamp(transitionPosition - gameTime.ElapsedGameTime.Milliseconds / (float)transitionOnTime.TotalMilliseconds, 0.0f, 1.0f);
                if (transitionPosition == 0.0f)
                {
                    state = ScreenState.Hidden;
                }
            }

            collisionManager.GenerateCollisions();
            collisionManager.ProcessCollisions();
            nodesToUpdate.Update(gameTime);
        }

        #endregion

        #region Drawing

        public virtual void Begin()
        {
            spriteBatch.Begin();
        }

        public virtual void Draw(GameTime gameTime)
        {
            nodesToDraw.Draw(gameTime, spriteBatch);   
        }

        public virtual void End()
        {
            spriteBatch.End();
        }

        public void TransitionStore(GameTime gameTime)
        {

            Game.GraphicsDevice.SetRenderTarget(0, renderTarget);
            Game.GraphicsDevice.Clear(Color.Black);

            Begin();
            Draw(gameTime);
            End();

            Game.GraphicsDevice.SetRenderTarget(0, null);
            
        }

        public void TransitionDraw(GameTime gameTime)
        {
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);

            Game.GraphicsDevice.Textures[1] = transitionMask;

            transitionEffect.Parameters["TransitionPosition"].SetValue(transitionPosition);

            transitionEffect.Begin();
            transitionEffect.CurrentTechnique.Passes[0].Begin();

            spriteBatch.Draw(renderTarget.GetTexture(), Vector2.Zero, Color.White);

            transitionEffect.CurrentTechnique.Passes[0].End();
            transitionEffect.End();

            spriteBatch.End();
        }

        #endregion

        #region Registering

        public void Register(GameNode node)
        {
            nodesToUpdate.Register(node);
        }

        public void Register(DrawableGameNode node)
        {
            nodesToUpdate.Register(node);
            nodesToDraw.Register(node);
        }

        public void Register(CollidableGameNode node)
        {
            nodesToUpdate.Register(node);
            nodesToDraw.Register(node);
            collisionManager.Register(node);
        }

        #endregion
    }
}
